import socket
import urllib
from urllib import request, error


"""
urllib 的 error 模块定义了由 request 模块产生的异常。如果出现了问题，request 模块便会抛出 error 模块中定义的异常。
"""


# 示例1 URLError异常捕获
"""
URLError 类来自 urllib 库的 error 模块，它继承自 OSError 类，是 error 异常模块的基类，由 request 模块产生的异常都可以通过捕获这个类来处理。
"""
# try:
#     response = request.urlopen('https://cuiqingcai.com/404')
# except error.URLError as e:
#     print(e.reason)


# 示例2 HTTPError 异常捕获
"""
它是 URLError 的子类，专门用来处理 HTTP 请求错误，比如认证请求失败等。它有如下 3 个属性。
code：返回 HTTP 状态码，比如 404 表示网页不存在，500 表示服务器内部错误等。
reason：同父类一样，用于返回错误的原因。
headers：返回请求头。
"""
# try:
#     response = request.urlopen('https://cuiqingcai.com/404')
# except error.HTTPError as e:
#     print(e.reason, e.code, e.headers, sep='\n')


# 示例3 比较好的异常处理写法
"""
因为 URLError 是 HTTPError 的父类，所以可以先选择捕获子类的错误，再去捕获父类的错误
也就是 做到先捕获 HTTPError，获取它的错误原因、状态码、headers 等信息。如果不是 HTTPError 异常，就会捕获 URLError 异常，输出错误原因。最后，用 else 来处理正常的逻辑。这是一个较好的异常处理写法
"""

# try:
#     response = request.urlopen('https://cuiqingcai.com/404')
# except error.HTTPError as e:
#     print(e.reason, e.code, e.headers, sep='\n')
# except error.URLError as e:
#     print(e.reason)
# else:
#     print('Request Successfully')


#示例4 返回的错误信息不是字符串，而是一个对象
"""
有时候，reason 属性返回的不一定是字符串，也可能是一个对象。再看下面的实例：
"""
# 可以发现，reason 属性的结果是 socket.timeout 类。所以，这里我们可以用 isinstance 方法来判断它的类型，作出更详细的异常判断。
try:
    response = urllib.request.urlopen('https://www.baidu.com', timeout=0.01)
except urllib.error.URLError as e:
    print(type(e.reason))
    if isinstance(e.reason, socket.timeout):
        print('TIME OUT')